package retrofit2.converter.gson;

import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Type;

import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;
import retrofit2.annotation.Adapter;
import retrofit2.annotation.Data;
import retrofit2.annotation.MsgData;
import retrofit2.annotation.StringData;
import retrofit2.converter.gson.adapter.CustomResponseAdapter;
import retrofit2.converter.gson.adapter.GsonResponseAdapter;
import retrofit2.converter.gson.adapter.ResponseAdapter;
import retrofit2.converter.gson.adapter.StringResponseAdapter;

public class JoyrunConverterFactory extends Converter.Factory {

	/**
	 * Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and
	 * decoding from JSON (when no charset is specified by a header) will use UTF-8.
	 */
	public static JoyrunConverterFactory create() {
		return create(new Gson());
	}

	/**
	 * Create an instance using {@code gson} for conversion. Encoding to JSON and
	 * decoding from JSON (when no charset is specified by a header) will use UTF-8.
	 */
	public static JoyrunConverterFactory create(Gson gson) {
		return new JoyrunConverterFactory(gson);
	}

	private final Gson gson;

	private JoyrunConverterFactory(Gson gson) {
		if (gson == null)
			throw new NullPointerException("gson == null");
		this.gson = gson;
	}

	@Override
	public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {

		// 特殊ResponseBodyConverter
		for (Annotation annotation : annotations) {
			// 仅解析json中的msg字段
			if (annotation instanceof MsgData) {
				return new JoyrunResponseBodyConverter<>(new StringResponseAdapter(), "msg");
			}

			if (annotation instanceof StringData) {
				return new StringResponseBodyConverter();
			}
		}

		// 数据字段名
		String name = "data";

		for (Annotation annotation : annotations) {
			if (annotation instanceof Data) {
				name = ((Data) annotation).value();
				break;
			}
		}

		//  自定义adapter
		for (Annotation annotation : annotations) {
			if (annotation instanceof Adapter) {
				Class<? extends CustomResponseAdapter> adpaterClazz = ((Adapter) annotation).adapter();

				try {
					// 获取有 以gson参数的 构造函数
					Constructor<? extends CustomResponseAdapter> constructor = adpaterClazz.getConstructor(Gson.class);
					CustomResponseAdapter                        adapter     = constructor.newInstance(gson);

					return new JoyrunResponseBodyConverter<>(adapter, name);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}

		TypeAdapter<?>  adapter         = gson.getAdapter(TypeToken.get(type));
		ResponseAdapter responseAdapter = new GsonResponseAdapter<>(adapter);

		return new JoyrunResponseBodyConverter<>(responseAdapter, name);
	}

	@Override
	public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
		TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
		return new GsonRequestBodyConverter<>(gson, adapter);
	}
}
